
#include <gtest\gtest.h>
#include <vector>
#include <iostream>
#include <boost/smart_ptr.hpp>
#include <allegro5/allegro.h>
#include <allegro5/allegro_primitives.h>
#include <allegro5/allegro_native_dialog.h>


#include "Bitmap.h"
#include "colour.h"
#include "Digdug.h"
#include "Display.h"
#include "Game.h"
#include "GlobalVariables.h"
#include "LevelLoader.h"
#include "Map.h"
#include "Monster.h"
#include "Movables.h"
#include "Point.h"
#include "Projectile.h"
#include "Utilities.h"
#include "Keyboard.h"

using boost::shared_ptr;
using boost::scoped_ptr;
using std::vector;

//bool init = al_init();
//bool prim = al_init_primitives_addon();

//Create a display object which initializes Allegro.
//Used for some of the graphical unit tests.
boost::shared_ptr<Display> display_ptr(new Display);

//bool init = al_init();	
//bool prim_init = al_init_primitives_addon();

/////////////////////////////////////
//		Tests for Point Class
/////////////////////////////////////

TEST(Point, identicalPointsAreEqual)
{
	Point point1(25, 25);
	Point point2(25, 25);

	EXPECT_TRUE(point1 == point2);
}

TEST(Point, nonIdenticalPointsAreNotEqual)
{
	Point point1(25, 25);
	Point point2(30, 25);

	EXPECT_FALSE(point1 == point2);
}

/////////////////////////////////////
//		Tests for Utilities
/////////////////////////////////////


//Tests for delta function in utilities header file
TEST(Utilities, deltaFunctionReturnsCorrectValuesForUPDirection)
{
	vector<int> delta_values = delta(UP);

	EXPECT_EQ(delta_values.at(0), 0);
	EXPECT_EQ(delta_values.at(1), -1);
}

TEST(Utilities, deltaFunctionReturnsCorrectValuesForDOWNDirection)
{
	vector<int> delta_values = delta(DOWN);

	EXPECT_EQ(delta_values.at(0), 0);
	EXPECT_EQ(delta_values.at(1), 1);
}

TEST(Utilities, deltaFunctionReturnsCorrectValuesForLEFTDirection)
{
	vector<int> delta_values = delta(LEFT);

	EXPECT_EQ(delta_values.at(0), -1);
	EXPECT_EQ(delta_values.at(1), 0);
}

TEST(Utilities, deltaFunctionReturnsCorrectValuesForRIGHTDirection)
{
	vector<int> delta_values = delta(RIGHT);

	EXPECT_EQ(delta_values.at(0), 1);
	EXPECT_EQ(delta_values.at(1), 0);
}


//Tests for contains function in utilities header file
TEST(Utilities, doesNotContainTestedDirectionIfEmptyDirectionVectorIsTested)
{
	vector<Direction> directions;
	directions.clear();

	EXPECT_FALSE(contains(directions, UP));
	EXPECT_FALSE(contains(directions, DOWN));
	EXPECT_FALSE(contains(directions, LEFT));
	EXPECT_FALSE(contains(directions, RIGHT));
}


TEST(Utilities, containsDirectionIfTestedDirectionIsFoundOnceInTestedVector)
{
	vector<Direction> directions;
	directions.push_back(LEFT);
	directions.push_back(RIGHT);
	directions.push_back(DOWN);
	directions.push_back(LEFT);

	EXPECT_TRUE(contains(directions, RIGHT));
}


TEST(Utilities, containsDirectionIfTestedDirectionIsFoundMultipleTimesInTestedVector)
{
	vector<Direction> directions;
	directions.push_back(LEFT);
	directions.push_back(RIGHT);
	directions.push_back(DOWN);
	directions.push_back(LEFT);

	EXPECT_TRUE(contains(directions, LEFT));
}

TEST(Utilities, doesNotcontainDirectionIfTestedDirectionIsNotContainedInTestedVector)
{
	vector<Direction> directions;
	directions.push_back(LEFT);
	directions.push_back(RIGHT);
	directions.push_back(DOWN);
	directions.push_back(LEFT);

	EXPECT_FALSE(contains(directions, UP));
}

/////////////////////////////////////
//		Tests for LevelLoader
/////////////////////////////////////

//LevelLoader throws a string when an invalid level is passed to the 
//constructor class. 
TEST(LevelLoader, throwsExceptionWhenLoadingFileThatDoesNotExist)
{
	EXPECT_THROW({LevelLoader invalidLevel(123);}, string );
}

//LevelLoaderClass creates an object without any throws when
//A file that corresponds to the given level exists
TEST(LevelLoader, aValidFileIsSucessfullyLoadedByConstructor)
{
	EXPECT_NO_THROW({LevelLoader validLevel(100);});
}

//The known position of digdug is correctly loaded from a file
TEST(LevelLoader, digdugsPositionIsCorrectlyLoadedFromFile)
{
	LevelLoader game_data(100);
	Point digdug_location(24,24);
	EXPECT_TRUE(game_data.getDigdugPosition() == digdug_location);
}

//All Monsters are correcly loaded from a file
TEST(LevelLoader, monstersPositionIsCorrectlyLoadedFromFile)
{	
	LevelLoader game_data(104);		
	vector <Point> loaded_monster_data = game_data.getMonstersPosition();
	vector <Point> expected_monster_data;
	
	expected_monster_data.push_back(Point(9,14));
	expected_monster_data.push_back(Point(39,14));

	EXPECT_TRUE(loaded_monster_data == expected_monster_data);
}

//Map Data is correctly loaded
TEST(LevelLoader, mapDataIsCorrectlyLoadedFromAFile)
{	
	LevelLoader game_data(102);		

	vector<vector<Movable_type>> expected_map;
	for(int x = 0; x < 50; x++)
	{
		expected_map.push_back(vector<Movable_type>());
		for(int y = 0; y < 50; y++)
		{
			if( x !=24 || y !=24)
				expected_map.back().push_back(SAND);
			else
				expected_map.back().push_back(HOLE);
		}
	}

	EXPECT_TRUE(expected_map == game_data.getMapData());
}


//For testing purposes a map starting at level_100, stored as a txt, is used to contain the data for the test map.
//The map level_100 contains sand except for a line of holes starting (25, 0) till (25, 25)


/////////////////////////////////////
//		Tests for Map Class
/////////////////////////////////////


TEST(Map, canIdentifyElementTypeAtGivenPositionOnMap)
{
	//First load the map with the level data. 
	
	LevelLoader test_level(100);
	Map test_map;
	test_map.set(test_level.getMapData()); // This loads a map containing sand and holes at positions listed above

	EXPECT_TRUE(test_map.positionType(Point(25, 5)) == HOLE);
	EXPECT_TRUE(test_map.positionType(Point(5, 5)) == SAND);

	EXPECT_FALSE(test_map.positionType(Point(5, 5)) == HOLE);
	EXPECT_FALSE(test_map.positionType(Point(25, 5)) == SAND);

}

//Test plotting of movables to map

TEST(Map, canPlotDigdugWithGivenRadiusToPositionOnMap)
{
//First load the map with the level data. 
	
	LevelLoader test_level(100);
	Map test_map;
	test_map.set(test_level.getMapData()); // This loads a map containing sand and holes, with no movables

	//check that digdug is not at test position
	EXPECT_FALSE( test_map.positionType(Point(24, 24)) == DIGDUG );
	EXPECT_FALSE( test_map.positionType(Point(23, 23)) == DIGDUG );
	EXPECT_FALSE( test_map.positionType(Point(23, 25)) == DIGDUG );


	test_map.plotMovable(DIGDUG, Point(24, 24), 1);

	EXPECT_TRUE( test_map.positionType(Point(24, 24)) == DIGDUG );
	EXPECT_TRUE( test_map.positionType(Point(23, 23)) == DIGDUG );
	EXPECT_TRUE( test_map.positionType(Point(23, 25)) == DIGDUG );
	EXPECT_FALSE( test_map.positionType(Point(26, 25)) == DIGDUG );
}

TEST(Map, canPlotMonsterWithGivenRadiusToPositionOnMap)
{
//First load the map with the level data. 
	
	LevelLoader test_level(100);
	Map test_map;
	test_map.set(test_level.getMapData()); // This loads a map containing sand and holes, with no movables

	//check that monster is not at test position
	EXPECT_FALSE( test_map.positionType(Point(24, 24)) == MONSTER );
	EXPECT_FALSE( test_map.positionType(Point(23, 23)) == MONSTER );
	EXPECT_FALSE( test_map.positionType(Point(23, 25)) == MONSTER );


	test_map.plotMovable(MONSTER, Point(24, 24), 1);

	EXPECT_TRUE( test_map.positionType(Point(24, 24)) == MONSTER );
	EXPECT_TRUE( test_map.positionType(Point(23, 23)) == MONSTER );
	EXPECT_TRUE( test_map.positionType(Point(23, 25)) == MONSTER );
	EXPECT_FALSE( test_map.positionType(Point(26, 25)) == MONSTER );
}

TEST(Map, canPlotProjectileWithGivenRadiusToPositionOnMap)
{
//First load the map with the level data. 
	
	LevelLoader test_level(100);
	Map test_map;
	test_map.set(test_level.getMapData()); // This loads a map containing sand and holes, with no movables

	//check that projectile is not at test position
	EXPECT_FALSE( test_map.positionType(Point(24, 24)) ==	PROJECTILE );
	EXPECT_FALSE( test_map.positionType(Point(23, 23)) == PROJECTILE );
	EXPECT_FALSE( test_map.positionType(Point(23, 25)) == PROJECTILE );


	test_map.plotMovable(PROJECTILE, Point(24, 24), 1);

	EXPECT_TRUE( test_map.positionType(Point(24, 24)) == PROJECTILE );
	EXPECT_TRUE( test_map.positionType(Point(23, 23)) == PROJECTILE );
	EXPECT_TRUE( test_map.positionType(Point(23, 25)) == PROJECTILE );
	EXPECT_FALSE( test_map.positionType(Point(26, 25)) == PROJECTILE );
}

//Test removal of movables from map

TEST(Map, canRemoveMovableWithGivenRadiusFromPositionOnMap)
{
//First load the map with the level data. 
	
	LevelLoader test_level(100);
	Map test_map;
	test_map.set(test_level.getMapData()); // This loads a map containing sand and holes, with no movables

	//Plot Digdug on map
	test_map.plotMovable(DIGDUG, Point(24, 24), 1);


	//check that digdug is at test position
	EXPECT_TRUE( test_map.positionType(Point(24, 24)) == DIGDUG );
	EXPECT_TRUE( test_map.positionType(Point(23, 23)) == DIGDUG );
	EXPECT_TRUE( test_map.positionType(Point(23, 25)) == DIGDUG );

	//Remove Digdug From Map
	test_map.removeMovable(Point(24, 24), 1);

	EXPECT_FALSE( test_map.positionType(Point(24, 24)) == DIGDUG );
	EXPECT_FALSE( test_map.positionType(Point(23, 23)) == DIGDUG );
	EXPECT_FALSE( test_map.positionType(Point(23, 25)) == DIGDUG );
}


/////////////////////////////////////
//		Tests for Digdug Class
/////////////////////////////////////

TEST(Digdug, canMoveDigDugInSpecifiedDirectionThroughHole)
{
	//Create digdug at given position
	Digdug digdug(Point(23, 25));
	
	//Load map with level data
	LevelLoader test_level(104);
	Map map;
	map.set(test_level.getMapData()); // This loads a map containing sand and holes, with no movables

	//Plot Digdug on map
	map.plotMovable(DIGDUG, digdug.location(), 1);

	//Tell digdug to move LEFT
	digdug.allowMove(LEFT);
	
	EXPECT_TRUE(digdug.move(map) == CAN_MOVE);

}

TEST(Digdug, digDugIdentifiesWhenHeHasMovedIntoSand)
{
	//Create digdug at given position
	Digdug digdug(Point(23, 25));
	
	//Load map with level data
	LevelLoader test_level(100);
	Map map;
	map.set(test_level.getMapData()); // This loads a map containing sand and holes, with no movables

	//Plot Digdug on map
	map.plotMovable(DIGDUG, digdug.location(), 1);

	//Tell digdug to move LEFT
	digdug.allowMove(LEFT);
	
	EXPECT_TRUE(digdug.move(map) == EAT_SAND);

}

TEST(Digdug, digdugDiesWhenMovingIntoMonster)
{
	//Create Digdug at given position
	Digdug digdug(Point(24, 10));
	//create monster at one movable location above digdug
	Monster monster(Point(24, digdug.location().y() - 2*RADIUS_OF_MOVABLE - 1)); 
	
	//Load map with level data
	LevelLoader test_level(100);
	Map map;
	map.set(test_level.getMapData()); 


	map.plotMovable(PROJECTILE, digdug.location(), RADIUS_OF_MOVABLE);
	map.plotMovable(MONSTER, monster.location(), RADIUS_OF_MOVABLE);

	digdug.allowMove(UP);
	
	EXPECT_TRUE(digdug.move(map) == DIGDUG_DEAD);
}

/////////////////////////////////////
//		Tests for Projectile Class
/////////////////////////////////////

TEST(Projectile, canMovePrjectileInSpecifiedDirectionThroughHole)
{
	//Create Projectile at given position
	Projectile projectile(Point(24, 10));
	
	//Load map with level data
	LevelLoader test_level(100);
	Map map;
	map.set(test_level.getMapData()); 

	//Plot Digdug on map
	map.plotMovable(PROJECTILE, projectile.location(), 1);

	//Tell projectile to move UP to position containing hole
	projectile.allowMove(UP);
	
	EXPECT_TRUE(projectile.move(map) == CAN_MOVE);
}

TEST(Projectile, projectileHasCollisionWhenMovingThroughSand)
{
	//Create Projectile at given position in sand
	Projectile projectile(Point(30, 30));
	
	//Load map with level data
	LevelLoader test_level(100);
	Map map;
	map.set(test_level.getMapData());


	map.plotMovable(PROJECTILE, projectile.location(), 1);

	projectile.allowMove(RIGHT);
	
	EXPECT_TRUE(projectile.move(map) == COLLISION);
}

TEST(Projectile, projectileKillsMonsterWhenMovingIntoMonster)
{
	//Create Projectile at given position
	Projectile projectile(Point(24, 10));
	//create monster at one movable location above the projectile
	Monster monster(Point(24, projectile.location().y() - 2*RADIUS_OF_MOVABLE - 1)); 
	
	//Load map with level data
	LevelLoader test_level(100);
	Map map;
	map.set(test_level.getMapData()); 


	map.plotMovable(PROJECTILE, projectile.location(), RADIUS_OF_MOVABLE);
	map.plotMovable(MONSTER, monster.location(), RADIUS_OF_MOVABLE);

	projectile.allowMove(UP);
		
	EXPECT_TRUE(projectile.move(map) == MONSTER_DEAD);
}

/////////////////////////////////////
//		Tests for Movables Class
/////////////////////////////////////

TEST(Movables, movableHasCollisionWhenTryingToMoveOutOfTopAndLeftGameBoundaries)
{
	//Load map with level containing only holes
	LevelLoader test_level(104);
	Map map;
	map.set(test_level.getMapData()); // This loads a map containing sand and holes, with no movables

	//Create a movable at top left corner
	scoped_ptr<Movables> movable_ptr(new Digdug(Point(RADIUS_OF_MOVABLE, RADIUS_OF_MOVABLE)));

	EXPECT_TRUE(movable_ptr->checkMoveInDirection(movable_ptr->location(), UP, map) == COLLISION);
	EXPECT_TRUE(movable_ptr->checkMoveInDirection(movable_ptr->location(), LEFT, map) == COLLISION);
}

TEST(Movables, movableHasCollisionWhenTryingToMoveOutOfBottomAndRightGameBoundaries)
{
	//Load map with level containing only holes
	LevelLoader test_level(104);
	Map map;
	map.set(test_level.getMapData()); // This loads a map containing sand and holes, with no movables

	//Create a movable at bottom right corner
	scoped_ptr<Movables> movable_ptr(new Monster(Point(GAME_GRID_ELEMENTS - RADIUS_OF_MOVABLE - 1, GAME_GRID_ELEMENTS - RADIUS_OF_MOVABLE - 1)));

	EXPECT_TRUE(movable_ptr->checkMoveInDirection(movable_ptr->location(), DOWN, map) == COLLISION);
	EXPECT_TRUE(movable_ptr->checkMoveInDirection(movable_ptr->location(), RIGHT, map) == COLLISION);
}

TEST(Movables, movableObjectsCanBeMovedUsingPointersToParentClassWithoutKnowingTheIdentityOfTheDerivedClass)
{
	//Load map with level containing only holes
	LevelLoader test_level(104);
	Map map;
	map.set(test_level.getMapData()); // This loads a map containing sand and holes, with no movables

	//Create a movable at bottom right corner
	boost::shared_ptr<Movables> movable_ptr1(new Monster(Point(10, 10)));
	boost::shared_ptr<Movables> movable_ptr2(new Digdug(Point(25, 25)));
	boost::shared_ptr<Movables> movable_ptr3(new Projectile(Point(40, 40)));

	movable_ptr1->allowMove(DOWN);
	movable_ptr2->allowMove(RIGHT);
	movable_ptr3->allowMove(UP);

	//Test that the movable is allowed to move.
	EXPECT_EQ(movable_ptr1->move(map), CAN_MOVE);
	EXPECT_EQ(movable_ptr2->move(map), CAN_MOVE);
	EXPECT_EQ(movable_ptr3->move(map), CAN_MOVE);
}


TEST(Movables, movableObjectsAreMovedInTheCorrectDirectionUsingPointersToParentClassWithoutKnowingTheIdentityOfTheDerivedClass)
{
	//Load map with level containing only holes
	LevelLoader test_level(104);
	Map map;
	map.set(test_level.getMapData()); // This loads a map containing sand and holes, with no movables

	//Create a movable at bottom right corner
	boost::shared_ptr<Movables> movable_ptr1(new Monster(Point(10, 10)));
	boost::shared_ptr<Movables> movable_ptr2(new Digdug(Point(25, 25)));
	boost::shared_ptr<Movables> movable_ptr3(new Projectile(Point(40, 40)));

	movable_ptr1->allowMove(DOWN);
	movable_ptr2->allowMove(RIGHT);
	movable_ptr3->allowMove(UP);

	EXPECT_EQ(movable_ptr1->location(), Point(10,11));
	EXPECT_EQ(movable_ptr2->location(), Point(26,25));
	EXPECT_EQ(movable_ptr3->location(), Point(40,39));

}
//////////////////////////////////////////////
//		Automated Tests For Display Class
//////////////////////////////////////////////


TEST (Display, theDisplayClassSetsUpAllegroWithoutAnyProblems)
{
	ASSERT_NO_THROW({boost::shared_ptr<Display> display_ptr_temp(new Display);});
}


TEST (Display, frameRateSetupByAllegroTriggersEventWithinExpectedTimeRange)
{

	ALLEGRO_EVENT ev; 
	boost::shared_ptr<Display> display_ptr_temp(new Display);

	display_ptr_temp->startTimer(); //Start the timer
	clock_t begin=clock();			//Start the clock
	al_wait_for_event(display_ptr_temp->event_queue(), &ev); //Wait for 
	clock_t end=clock();
	
	float frame_rate_measured = float(diffclock(end,begin));
	float frame_rate_expected = (1/(float)FPS)*1000;	//Milliseconds

	EXPECT_TRUE(frame_rate_measured >  frame_rate_expected*0.9);
	EXPECT_TRUE(frame_rate_expected*1.1 > frame_rate_measured);

}

//////////////////////////////////////////////
//		Graphical Tests Requiring User Input
//////////////////////////////////////////////

//////////////////////////////////////////////
//		Tests For Display Class
//////////////////////////////////////////////

TEST(Display, drawsScoreBoxCorrectlyandDisplaysCorrectScores)
{
	display_ptr->clearBuffer();
	display_ptr->drawScoreBox(100, 5, 1000, 10);
	display_ptr->update();

	int answer = display_ptr->showNativeDialogMessageQuestion( "Drawing of Score Box",
	"The score box should be visible on the right hand side of the screen. \nThe following values are expected: \nScore: 100, \nLives: 5, \nHigh Score: 1000, \nLevel: 10. \nIf this is the case, please click 'Yes'. Else click 'No'");
		
	EXPECT_EQ(answer, 1);
}

TEST(Display, drawsMapCorrectly)
{
	//Load map with level containing only holes
	LevelLoader test_level(102);
	Map map;
	map.set(test_level.getMapData()); // This loads a map containing sand and holes, with no movables
	
	display_ptr->clearBuffer();
	display_ptr->drawMap(map);
	display_ptr->update();

	int answer = display_ptr->showNativeDialogMessageQuestion( "Drawing of Map",
	"A map consisting of sand with one small square hole in the middle should be visible. \nIf this is the case, please click 'Yes'. Else click 'No'");
		
	EXPECT_EQ(answer, 1);
}

TEST(Display, drawsMonstersCorrectly)
{
	Monster monster(Point(25, 25));
	vector<Monster> monster_vec;
	monster_vec.push_back(monster);

	display_ptr->clearBuffer();
	display_ptr->drawMonsters(monster_vec);
	display_ptr->update();

	int answer = display_ptr->showNativeDialogMessageQuestion( "Drawing of Monsters","Do you see a monster in the middle of the playing grid?");
		
	EXPECT_EQ(answer, 1);
}

TEST(Display, drawsDigdugCorrectly)
{
	Digdug digdug(Point(25, 25));
	
	display_ptr->clearBuffer();
	display_ptr->drawDigdug(digdug);
	display_ptr->update();

	int answer = display_ptr->showNativeDialogMessageQuestion( "Drawing of Dig Dug","Do you see Dig Dug in the middle of the playing grid?");
		
	EXPECT_EQ(answer, 1);
}

TEST(Display, drawsProjectileCorrectly)
{
	Digdug digdug(Point(20, 25));
	Projectile projectile(Point(25, 25));
	//The projectile must be set to shooting mode in order to be drawn
	projectile.allowMove(RIGHT);

	display_ptr->clearBuffer();
	//The projectile is drawn extending from Digdug's position
	display_ptr->drawProjectile(projectile, digdug);
	display_ptr->update();

	int answer = display_ptr->showNativeDialogMessageQuestion( "Drawing of Projectile","Do you see a projectile in the extending to the right in middle of the playing grid?");
		
	EXPECT_EQ(answer, 1);
}

//////////////////////////////////////////////
//		Tests For Game Class
//////////////////////////////////////////////

TEST(Display, userCanMoveDigdugInSpecifiedDirection)
{
	Game game(102, 1);
	
	Action action = NO_ACTION;
	bool arrow_keys[4] = {false, false, false, false};
	bool shoot_key = false; 
	bool pause_key = false; 
	bool exit_key = false; 
	bool is_exit = false; 

	
	display_ptr->showNativeDialogMessageOK("Start test", "Instruction", "Test that Dig Dug can be moved in selected directions by using the arrow keys.\n\nMove digdug in chosen directions by pressing the arrow keys. \nWhen you are done with the test press the Escape key. \nClick OK to start the test.");

	while(is_exit == false)
	{
		ALLEGRO_EVENT ev; 
		al_wait_for_event(display_ptr->event_queue(), &ev);

		if (ev.type ==ALLEGRO_EVENT_KEY_DOWN ||ev.type == ALLEGRO_EVENT_KEY_UP)
		{
			keyboard_event(ev, action, arrow_keys, shoot_key, pause_key, exit_key, is_exit);
		}

		game.update(action);

		//Draw the Map
		display_ptr->drawMap(game.map());
	
		//Draw the Monsters
		display_ptr->drawMonsters(game.monsters());

		//Draw Digdug
		display_ptr->drawDigdug(game.digdug());

		//Draw Projectile
		display_ptr->drawProjectile(game.projectile(), game.digdug());

		//Flip the display
		display_ptr->update();

		//Clear the buffer
		display_ptr-> clearBuffer();
	}
	int answer = display_ptr->showNativeDialogMessageQuestion( "User Control of Dig Dug","Did Dig Dug move in the chosen directions?");
		
	EXPECT_EQ(answer, 1);
}

TEST(Display, monstersTrackDigdugAsDigdugMovesAroundScreen)
{
	Game game(100, 1);
	
	Action action = NO_ACTION;
	bool arrow_keys[4] = {false, false, false, false};
	bool shoot_key = false; 
	bool pause_key = false; 
	bool exit_key = false; 
	bool is_exit = false; 

	
	display_ptr->showNativeDialogMessageOK("Start test", "Instruction", "Test whether the monster follows Dig Dug as he moves around the screen. \n\nMove digdug in chosen directions by pressing the arrow keys.\nDo not move into the monster \nWhen you are done with the test press the Escape key. \nClick OK to start the test.");

	while(is_exit == false)
	{
		ALLEGRO_EVENT ev; 
		al_wait_for_event(display_ptr->event_queue(), &ev);

		if (ev.type ==ALLEGRO_EVENT_KEY_DOWN ||ev.type == ALLEGRO_EVENT_KEY_UP)
		{
			keyboard_event(ev, action, arrow_keys, shoot_key, pause_key, exit_key, is_exit);
		}

		game.update(action);

		//Draw the Map
		display_ptr->drawMap(game.map());
	
		//Draw the Monsters
		display_ptr->drawMonsters(game.monsters());

		//Draw Digdug
		display_ptr->drawDigdug(game.digdug());

		//Draw Projectile
		display_ptr->drawProjectile(game.projectile(), game.digdug());

		//Flip the display
		display_ptr->update();

		//Clear the buffer
		display_ptr-> clearBuffer();
	}
	int answer = display_ptr->showNativeDialogMessageQuestion( "Routing of Monsters","Did the monster follow digdug as he moved around the screen?");
		
	EXPECT_EQ(answer, 1);
}

TEST(Display, monstersBecomeGhostsAndMoveIntoTunnelContainingDigdugIfTheyHaveNoDirectPathToDigdug)
{
	Game game(103, 1);
	
	Action action = NO_ACTION;
	bool arrow_keys[4] = {false, false, false, false};
	bool shoot_key = false; 
	bool pause_key = false; 
	bool exit_key = false; 
	bool is_exit = false; 

	
	display_ptr->showNativeDialogMessageOK("Start test", "Instruction", "Test that the monsters turn into ghosts and move into Dig Dug's tunnel. \n\nMove digdug in chosen directions by pressing the arrow keys.\nDo not move into the tunnels containing the monsters \nWhen you are done with the test press the Escape key. \nClick OK to start the test.");

	while(is_exit == false)
	{
		ALLEGRO_EVENT ev; 
		al_wait_for_event(display_ptr->event_queue(), &ev);

		if (ev.type ==ALLEGRO_EVENT_KEY_DOWN ||ev.type == ALLEGRO_EVENT_KEY_UP)
		{
			keyboard_event(ev, action, arrow_keys, shoot_key, pause_key, exit_key, is_exit);
		}

		game.update(action);

		//Draw the Map
		display_ptr->drawMap(game.map());
	
		//Draw the Monsters
		display_ptr->drawMonsters(game.monsters());

		//Draw Digdug
		display_ptr->drawDigdug(game.digdug());

		//Draw Projectile
		display_ptr->drawProjectile(game.projectile(), game.digdug());

		//Flip the display
		display_ptr->update();

		//Clear the buffer
		display_ptr-> clearBuffer();
	}
	int answer = display_ptr->showNativeDialogMessageQuestion( "Transformation of monsters","Did the monsters turn into ghosts and move into Dig Dug's tunnel after they could not track Dig Dug?");
		
	EXPECT_EQ(answer, 1);
}

TEST(Display, monsterInflatesAndDiesIfUserHoldsDownTheShootKeyWhileDigdugIsFacingTheMonster)
{
	Game game(101, 1);
	
	Action action = NO_ACTION;
	bool arrow_keys[4] = {false, false, false, false};
	bool shoot_key = false; 
	bool pause_key = false; 
	bool exit_key = false; 
	bool is_exit = false; 

	
	display_ptr->showNativeDialogMessageOK("Start test", "Instruction", "Test whether a monster can be inflated and destroyed using Dig Dug's projectile. \n\nFace Dig Dug upwards by pressing the UP key. \nPress and hold the Spacebar to shoot. \nPress Escape after the monster explodes. \n\nClick OK to start the test.");

	while(is_exit == false)
	{
		ALLEGRO_EVENT ev; 
		al_wait_for_event(display_ptr->event_queue(), &ev);

		if (ev.type ==ALLEGRO_EVENT_KEY_DOWN ||ev.type == ALLEGRO_EVENT_KEY_UP)
		{
			keyboard_event(ev, action, arrow_keys, shoot_key, pause_key, exit_key, is_exit);
		}

		game.update(action);

		//Draw the Map
		display_ptr->drawMap(game.map());
	
		//Draw the Monsters
		display_ptr->drawMonsters(game.monsters());

		//Draw Digdug
		display_ptr->drawDigdug(game.digdug());

		//Draw Projectile
		display_ptr->drawProjectile(game.projectile(), game.digdug());

		//Flip the display
		display_ptr->update();

		//Clear the buffer
		display_ptr-> clearBuffer();
	}
	int answer = display_ptr->showNativeDialogMessageQuestion( "Destruction of monsters","Did the monster inflate and explode when the shoot key was held down?");
		
	EXPECT_EQ(answer, 1);
}

TEST(Display, theNextLevelIsLoadedAfterAllMonstersOnALevelAreDestroyed)
{
	Game game(100, 2);
	
	Action action = NO_ACTION;
	bool arrow_keys[4] = {false, false, false, false};
	bool shoot_key = false; 
	bool pause_key = false; 
	bool exit_key = false; 
	bool is_exit = false; 

	
	display_ptr->showNativeDialogMessageOK("Start test", "Instruction", "Test whether the game proceeds to the next level when all monsters on a level have been killed.\n\nFace Dig Dug upwards by pressing the UP key. \nPress and hold the Spacebar to shoot. \Press Escape after the monster explodes. \n\nClick OK to start the test.");

	while(is_exit == false)
	{
		ALLEGRO_EVENT ev; 
		al_wait_for_event(display_ptr->event_queue(), &ev);

		if (ev.type ==ALLEGRO_EVENT_KEY_DOWN ||ev.type == ALLEGRO_EVENT_KEY_UP)
		{
			keyboard_event(ev, action, arrow_keys, shoot_key, pause_key, exit_key, is_exit);
		}

		game.update(action);

		//Draw the Map
		display_ptr->drawMap(game.map());
	
		//Draw the Monsters
		display_ptr->drawMonsters(game.monsters());

		//Draw Digdug
		display_ptr->drawDigdug(game.digdug());

		//Draw Projectile
		display_ptr->drawProjectile(game.projectile(), game.digdug());

		//Flip the display
		display_ptr->update();

		//Clear the buffer
		display_ptr-> clearBuffer();
	}
	int answer = display_ptr->showNativeDialogMessageQuestion( "Level testing","Did the game proceed to the next level after the monster was killed?");
		
	EXPECT_EQ(answer, 1);
}